/**
 *
 */
package jp.seraph.same.model;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.NullArgumentException;

import jp.seraph.jsade.model.AngleVelocityCalculator;
import jp.seraph.jsade.model.JointIdentifier;
import jp.seraph.jsmf.codec.PoseNameLinkMotionElement;
import jp.seraph.jsmf.codec.PoseNameLinkMotionElementData;
import jp.seraph.jsmf.motion.MotionElement;
import jp.seraph.jspf.pose.PoseManager;

/**
 *
 */
public class DefaultMotionElementModel extends AbstractViewModel implements MotionElementModel {
    public DefaultMotionElementModel(String aName, PoseManager aPoseManager, AngleVelocityCalculator aCalculator) {
        super(aName);
        mSelectedJoints = new HashSet<JointIdentifier>();
        mBasePoseName = null;
        mConditionElementName = "";
        mTiming = 0;
        mPoseManager = aPoseManager;
        mCalculator = aCalculator;
    }

    public DefaultMotionElementModel(PoseNameLinkMotionElement aModel){
        super(aModel.getName());
        PoseNameLinkMotionElementData tModelData = aModel.getElementData();
        mSelectedJoints = new HashSet<JointIdentifier>(tModelData.getIdentifiers());
        mBasePoseName = tModelData.getPoseName();
        mConditionElementName = tModelData.getConditionElementName();
        mTiming = tModelData.getStartPercentage();
        mPoseManager = aModel.getPoseManager();
        mCalculator = aModel.getCalculator();
    }

    private Set<JointIdentifier> mSelectedJoints;

    private String mBasePoseName;

    private String mConditionElementName;

    private int mTiming;

    private PoseManager mPoseManager;

    private AngleVelocityCalculator mCalculator;

    /**
     * @see jp.seraph.same.model.MotionElementModel#deselectJoint(jp.seraph.jsade.model.JointIdentifier)
     */
    public void deselectJoint(JointIdentifier aId) throws IllegalArgumentException {
        if (!mSelectedJoints.contains(aId))
            return;

        mSelectedJoints.remove(aId);
        fireChangedEvent();
    }

    /**
     * @see jp.seraph.same.model.MotionElementModel#getBasePose()
     */
    public String getBasePose() {
        return mBasePoseName;
    }

    /**
     * @see jp.seraph.same.model.MotionElementModel#getSelectedJoints()
     */
    public Set<JointIdentifier> getSelectedJoints() {
        return new HashSet<JointIdentifier>(mSelectedJoints);
    }

    /**
     *
     * @see jp.seraph.same.model.MotionElementModel#getConditionElementName()
     */
    public String getConditionElementName() {
        return mConditionElementName;
    }

    /**
     *
     * @see jp.seraph.same.model.MotionElementModel#setConditionElementName(java.lang.String)
     */
    public void setConditionElementName(String aConditionElementName) {
        mConditionElementName = aConditionElementName;
        fireChangedEvent();
    }

    /**
     * @see jp.seraph.same.model.MotionElementModel#getTiming()
     */
    public int getTiming() {
        return mTiming;
    }

    /**
     * @see jp.seraph.same.model.MotionElementModel#selectJoint(jp.seraph.jsade.model.JointIdentifier)
     */
    public void selectJoint(JointIdentifier aId) throws IllegalArgumentException {
        if (mSelectedJoints.contains(aId))
            return;

        mSelectedJoints.add(aId);
        fireChangedEvent();
    }

    /**
     * @see jp.seraph.same.model.MotionElementModel#setBasePose(java.lang.String)
     */
    public void setBasePose(String aPose) {
        if (aPose == null) {
            if (mBasePoseName == null)
                return;
        } else if (aPose.equals(mBasePoseName))
            return;

        mBasePoseName = aPose;
        fireChangedEvent();
    }

    /**
     * @see jp.seraph.same.model.MotionElementModel#setTiming(int)
     */
    public void setTiming(int aTiming) {
        if (aTiming == mTiming)
            return;

        mTiming = aTiming;
        fireChangedEvent();
    }

    public AngleVelocityCalculator getCalculator() {
        return mCalculator;
    }

    public void setCalculator(AngleVelocityCalculator aCalculator) {
        if (aCalculator == null)
            throw new NullArgumentException("aCalculator");

        mCalculator = aCalculator;
        fireChangedEvent();
    }

    public MotionElement toElement() {
        PoseNameLinkMotionElementData tData = new PoseNameLinkMotionElementData(getName(), getBasePose(), getConditionElementName(), getTiming(), getCalculator(), getSelectedJoints().toArray(new JointIdentifier[0]));
        PoseNameLinkMotionElement tElement = new PoseNameLinkMotionElement(mPoseManager, tData);

        return tElement;
    }
}
